﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Reflection;
using System.Data;

namespace Common
{
    public static class DataExtensions
    {
        public static List<T> MapToList<T>(this DbDataReader dr) where T : new()
        {
            var entities = new List<T>();
            if (dr != null && dr.HasRows)
            {
                var entity = typeof(T);
                var propDict = new Dictionary<string, PropertyInfo>();
                var props = entity.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                propDict = props.ToDictionary(p => p.Name.ToUpper(), p => p);

                while (dr.Read())
                {
                    T newObject = new T();
                    for (int index = 0; index < dr.FieldCount; index++)
                    {
                        if (propDict.ContainsKey(dr.GetName(index).ToUpper()))
                        {
                            var info = propDict[dr.GetName(index).ToUpper()];
                            if ((info != null) && info.CanWrite)
                            {
                                var val = dr.GetValue(index);
                                info.SetValue(newObject, (val == DBNull.Value) ? null : val, null);
                            }
                        }
                    }
                    entities.Add(newObject);
                }
                return entities;
            }
            return entities;
        }

        public static List<T> MapToList<T>(this DataTable dt) where T : new()
        {
            var entities = new List<T>();
            if (dt != null && dt.Rows.Count > 0)
            {
                var entity = typeof(T);
                var propDict = new Dictionary<string, PropertyInfo>();
                var props = entity.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                propDict = props.ToDictionary(p => p.Name.ToUpper(), p => p);

                //while (dr.Read())
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    var dr = dt.Rows[i];
                    T newObject = new T();
                    for (int index = 0; index < dt.Columns.Count; index++)
                    {
                        if (propDict.ContainsKey(dt.Columns[index].ColumnName.ToUpper()))
                        {
                            var info = propDict[dt.Columns[index].ColumnName.ToUpper()];
                            if ((info != null) && info.CanWrite)
                            {
                                var val = dr[index];
                                if (info.PropertyType.Name.Equals("String"))
                                {
                                    info.SetValue(newObject, (val == DBNull.Value) ? string.Empty : val.ToString(), null);
                                }
                                else
                                {
                                    try
                                    {
                                        info.SetValue(newObject, (val == DBNull.Value) ? null : val, null);
                                    }
                                    catch (ArgumentException ae)
                                    {
                                        if (val.GetType().Name.Equals("Boolean")
                                            && info.PropertyType.Name.Equals("Int32"))
                                        {
                                            info.SetValue(newObject, ((bool)val == true ? 1 : 0), null);
                                        }
                                        else
                                        {
                                            throw ae;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            // 移除字段名中的'_'
                            var columnName = dt.Columns[index].ColumnName.Replace("_", string.Empty).ToUpper();
                            if (propDict.ContainsKey(columnName))
                            {
                                var info = propDict[columnName];
                                if ((info != null) && info.CanWrite)
                                {
                                    var val = dr[index];
                                    if (info.PropertyType.Name.Equals("String"))
                                    {
                                        info.SetValue(newObject, (val == DBNull.Value) ? string.Empty : val.ToString(), null);
                                    }
                                    else
                                    {
                                        info.SetValue(newObject, (val == DBNull.Value) ? null : val, null);
                                    }
                                }
                            }
                        }
                    }
                    entities.Add(newObject);
                }
                return entities;
            }
            return entities;
        }

        public static List<string> MapToStringList(this DataTable dt, string columnName)
        {
            var entities = new List<string>();
            if (dt != null && dt.Rows.Count > 0)
            {
                //while (dr.Read())
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    var dr = dt.Rows[i];

                    var val = dr[columnName];
                    var newObject = val.ToString();
                    entities.Add(newObject);
                }
                return entities;
            }
            return entities;
        }

        /// <summary>
        /// DataTableToList的方法
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static IList<T> DataTableToList<T>(this DataTable dt)
        {
            if (dt == null)
            {
                return null;
            }
            if (dt.Rows.Count < 0)
            {
                return null;
            }
            //创建一个泛型集合对象
            IList<T> list = new List<T>();
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                //创建一个泛型对象
                T t = Activator.CreateInstance<T>();
                PropertyInfo[] propertyInfo = t.GetType().GetProperties();
                foreach (PropertyInfo item in propertyInfo)
                {
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        if (item.Name.ToLower().Equals(dt.Columns[j].ColumnName.ToLower()))
                        {
                            if (dt.Rows[i][j] != DBNull.Value)
                            {
                                item.SetValue(t, dt.Rows[i][j], null);
                            }
                            else
                            {
                                item.SetValue(t, null, null);
                            }
                            break;
                        }
                    }
                }
                list.Add(t);
            }
            return list;
        }

        /// <summary>
        /// DataTableToList的方法
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static void DataTableAppend(this DataTable DataTable1, DataTable DataTable2)
        {
            object[] obj = new object[DataTable1.Columns.Count];
            for (int i = 0; i < DataTable2.Rows.Count; i++)
            {
                DataTable2.Rows[i].ItemArray.CopyTo(obj, 0);
                DataTable1.Rows.Add(obj);
            } 
        } 
    }
}
